In [ ]:
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import scipy.stats as stats
In [ ]:
from matplotlib import rcParams

rcParams['figure.figsize'] = 12, 7
rcParams['lines.linewidth'] = 4
rcParams['xtick.labelsize'] = 'x-large'
rcParams['ytick.labelsize'] = 'x-large'
In [ ]:
data = pd.read_csv('Churn_Modelling.csv')

1. Descriptive Statistics¶

A. Apakah ada kolom dengan tipe data kurang sesuai, atau nama kolom dan isinya kurang sesuai?¶
Dengan data.info() kita bisa melihat apakah ada kolom dengan tipe data kurang sesusi atau tidak dan Dengan data.head() kita bisa melihat apakah ada nama kolom dan isinya kurang sesuai, dengan begitu dari data tersebut sudah aman sudah sesuai maka...¶
A: “Semua tipe data sudah sesuai”
B. Apakah ada kolom yang memiliki nilai kosong? Jika ada, apa saja?¶
Dengan data.info() kita bisa membandingkan jumlah kolom dan jumlah baris disni kita bisa lihat bahwa jumlahnya sudah sama yang berisi informasi tentang 10.000 pelanggan dari suatu bank, termasuk fitur-fitur seperti umur, jenis kelamin, saldo, produk, aktivitas, dll maka...¶
B: “tidak ada nilai kosong”
In [ ]:
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 10000 entries, 0 to 9999
Data columns (total 14 columns):
 #   Column           Non-Null Count  Dtype  
---  ------           --------------  -----  
 0   RowNumber        10000 non-null  int64  
 1   CustomerId       10000 non-null  int64  
 2   Surname          10000 non-null  object 
 3   CreditScore      10000 non-null  int64  
 4   Geography        10000 non-null  object 
 5   Gender           10000 non-null  object 
 6   Age              10000 non-null  int64  
 7   Tenure           10000 non-null  int64  
 8   Balance          10000 non-null  float64
 9   NumOfProducts    10000 non-null  int64  
 10  HasCrCard        10000 non-null  int64  
 11  IsActiveMember   10000 non-null  int64  
 12  EstimatedSalary  10000 non-null  float64
 13  Exited           10000 non-null  int64  
dtypes: float64(2), int64(9), object(3)
memory usage: 1.1+ MB
In [ ]:
# Ubah beberapa tipe data berikut
data = data.astype({
    'HasCrCard' : 'object',
    'IsActiveMember' : 'object',
    'Exited' : 'object'
})
In [ ]:
data.head()
Out[ ]:
RowNumber CustomerId Surname CreditScore Geography Gender Age Tenure Balance NumOfProducts HasCrCard IsActiveMember EstimatedSalary Exited
0 1 15634602 Hargrave 619 France Female 42 2 0.00 1 1 1 101348.88 1
1 2 15647311 Hill 608 Spain Female 41 1 83807.86 1 0 1 112542.58 0
2 3 15619304 Onio 502 France Female 42 8 159660.80 3 1 0 113931.57 1
3 4 15701354 Boni 699 France Female 39 1 0.00 2 0 0 93826.63 0
4 5 15737888 Mitchell 850 Spain Female 43 2 125510.82 1 1 1 79084.10 0

C. Apakah ada kolom yang memiliki nilai summary agak aneh?¶

(min/mean/median/max/unique/top/freq)

In [ ]:
## pengelompokan kategori
cats = ['Surname', 'Geography', 'Gender']
nums = ['RowNumber', 'CustomerId', 'CreditScore', 'Age', 'Tenure', 'Balance', 'NumOfProducts', 'HasCrCard', 'IsActiveMember', 'EstimatedSalary', 'Exited']
In [ ]:
data[nums].describe()
Out[ ]:
RowNumber CustomerId CreditScore Age Tenure Balance NumOfProducts HasCrCard IsActiveMember EstimatedSalary Exited
count 10000.00000 1.000000e+04 10000.000000 10000.000000 10000.000000 10000.000000 10000.000000 10000.00000 10000.000000 10000.000000 10000.000000
mean 5000.50000 1.569094e+07 650.528800 38.921800 5.012800 76485.889288 1.530200 0.70550 0.515100 100090.239881 0.203700
std 2886.89568 7.193619e+04 96.653299 10.487806 2.892174 62397.405202 0.581654 0.45584 0.499797 57510.492818 0.402769
min 1.00000 1.556570e+07 350.000000 18.000000 0.000000 0.000000 1.000000 0.00000 0.000000 11.580000 0.000000
25% 2500.75000 1.562853e+07 584.000000 32.000000 3.000000 0.000000 1.000000 0.00000 0.000000 51002.110000 0.000000
50% 5000.50000 1.569074e+07 652.000000 37.000000 5.000000 97198.540000 1.000000 1.00000 1.000000 100193.915000 0.000000
75% 7500.25000 1.575323e+07 718.000000 44.000000 7.000000 127644.240000 2.000000 1.00000 1.000000 149388.247500 0.000000
max 10000.00000 1.581569e+07 850.000000 92.000000 10.000000 250898.090000 4.000000 1.00000 1.000000 199992.480000 1.000000
In [ ]:
data[cats].describe()
Out[ ]:
Surname Geography Gender
count 10000 10000 10000
unique 2932 3 2
top Smith France Male
freq 32 5014 5457
In [ ]:
data.isna().sum()
Out[ ]:
RowNumber          0
CustomerId         0
Surname            0
CreditScore        0
Geography          0
Gender             0
Age                0
Tenure             0
Balance            0
NumOfProducts      0
HasCrCard          0
IsActiveMember     0
EstimatedSalary    0
Exited             0
dtype: int64

Nilai Summary Agak Aneh¶

Dalam data ini, jika "Tenure" diukur dalam tahun, maka nilai summary yang mungkin agak aneh atau memerlukan perhatian khusus adalah Kolom "Tenure": Nilai minimum 0 mungkin dianggap agak aneh jika "Tenure" diukur dalam tahun. Meskipun mungkin masih wajar jika ada pelanggan yang baru bergabung dalam tahun yang sama.

Selain itu, perbedaan yang signifikan antara mean dan median pada beberapa kolom juga dapat memerlukan perhatian khusus karena menunjukkan adanya distribusi data yang lebih merata atau keberadaan outlier yang mempengaruhi mean. Misalnya, perbedaan yang signifikan antara mean dan median pada "Balance" dan "EstimatedSalary."

Untuk memberikan insight yang lebih jelas yaitu

•Tenure" diukur dalam tahun.

•Tidak ada nilai negatif dalam kolom "Tenure."

•Nilai maksimum pada semua kolom dalam rentang yang masuk akal.

•Tidak ada nilai yang tidak valid atau string kosong dalam data ini.

Jadi, fokus utama adalah pada kolom "Tenure" yang memiliki nilai minimum 0 dan memerlukan pemahaman lebih lanjut sesuai dengan unit tahunnya.

Di dalam data ini pun ada beberapa kolom yg memiliki nilai median dan mean nya sangat signifikan yaitu

  • Kolom "Age":

Mean: 38.92

Median: 37.00

Perbedaan: 38.92 - 37.00 = 1.92

  • Kolom "Balance":

Mean: 76,485.89

Median: 97,198.54

Perbedaan: 76,485.89 - 97,198.54 = -20,712.65

  • Kolom "NumOfProducts":

Mean: 1.53

Median: 1.00

Perbedaan: 1.53 - 1.00 = 0.53

  • Kolom "EstimatedSalary":

Mean: 100,090.24

Median: 100,193.92

Perbedaan: 100,090.24 - 100,193.92 = -103.68

2. Univariate Analysis¶

Gunakan visualisasi untuk melihat distribusi masing-masing kolom (feature maupun target). Tuliskan hasil observasinya, misalnya jika ada suatu kolom yang distribusinya menarik (misal skewed, bimodal, ada outlier, ada nilai yang mendominasi, kategorinya terlalu banyak, dsb). Jelaskan juga apa yang harus di-follow up saat data pre-processing.¶

Distribution (Numeric)¶

In [1]:
import plotly.express as px
import plotly.subplots as sp
import pandas as pd

data = pd.read_csv('Churn_Modelling.csv')

kolom_plot = ['CreditScore','Age', 'Tenure', 'Balance','NumOfProducts','EstimatedSalary']
color = ['#cdc0b0','#F09EA7', '#F6CA94', '#C7CAFF','#89cff0','#C1EBC0']

for index in range(len(kolom_plot)):
  px.histogram(
      data,
      x = kolom_plot[index],
      marginal = 'box',
      color_discrete_sequence  = [color[index]],
      title = 'Distribution of ' + kolom_plot[index]
  ).update_traces(
      marker_line_width = 1,
      marker_line_color = 'white'
  ).update_layout(
    plot_bgcolor = 'rgba(0, 0, 0, 0)'
  ).show()
In [ ]:
 

Distribution (Categorical)¶

In [6]:
import plotly.express as px
import pandas as pd

data = pd.read_csv('Churn_Modelling.csv')

data_gender = data.groupby(['Gender'],as_index =False).agg(total_gender = ('Gender',pd.Series.count))
fig = px.pie(data_gender, values= 'total_gender', names='Gender')
fig.show ()
In [7]:
import plotly.express as px
import pandas as pd

data = pd.read_csv('Churn_Modelling.csv')

data_hascrcard = data.groupby(['HasCrCard'],as_index =False).agg(total_hascrcard = ('HasCrCard',pd.Series.count))
fig = px.pie(data_hascrcard, values= 'total_hascrcard', names='HasCrCard')
fig.show ()
In [8]:
import plotly.express as px
import pandas as pd

data = pd.read_csv('Churn_Modelling.csv')

data_isactive_member = data.groupby(['IsActiveMember'],as_index =False).agg(total_isactive_member = ('IsActiveMember',pd.Series.count))
fig = px.pie(data_isactive_member, values= 'total_isactive_member', names='IsActiveMember')
fig.show ()
In [5]:
import plotly.express as px
import pandas as pd

data = pd.read_csv('Churn_Modelling.csv')

data_exited = data.groupby(['Exited'],as_index =False).agg(total_exited = ('Exited',pd.Series.count))
fig = px.pie(data_exited, values= 'total_exited', names='Exited')
fig.show ()

Hasil Observasi¶

Berdasarkan hasil visualisasi di atas dapat disimpulkan bahwa :

  • Pada kolom CreditScore ternyata didapatkan banyak outlier yakni pada creditscore yang kurang dari 383. Selain itu, kolom creditScore juga memiliki distribusi left-skewed or negative-skewed. Artinya ekornya lebih panjang ke arah kiri, sehingga persebaran datanya lebih banyak di kiri.

  • Pada kolom age (umur) ternyata didapatkan banyak outlier yakni umur yang lebih dari 62 tahun. Untuk itu jika kita menggunakan alogaritma mechine learning yang sensitif terhadap outlier,maka kita perlu menenangani hal ini. Pada kolom age distribusinya miring ke kanan atau memiliki ekor yang lebih panjang ke arah kanan. Distribusi ini sering disebut distribusi right-skewed atau positive-skewed, karena persebaran datanya lebih banyak di kanan.

  • Pada kolom NumOfProducts didapatkan ada satu outlier yakni pada NumOfProducts lebih dari 3. Selain itu, pada kolom ini juga memiliki distribusi right-skewed atau positive-skewed. Artinya ekornya lebih panjang ke arah kanan, sehingga persebaran datanya lebih banyak di kanan.

  • Pada kolom Gender (jenis kelamin) didapatkan bahwa persentase jenis kelamin laki-laki sebesar 54.6% sedangkan perempuan sebesar 45.4%, sehingga ada selisih 9.2% antar keduanya.

  • Pada kolom HasCrCard ternyata didapatkan persentase nasabah yang memiliki kredit card lebih banyak dibandingkan yang tidak memiliki yaitu sebesar 70.5%.

  • Pada kolom IsActiveMember ternyata didapatkan bahwa persentase nasabah yang aktif sebesar 51.5% sedangkan nasabah yang tidak aktif sebesar 48.5%, sehingga ada selisih 3% antar keduanya.

  • Pada kolom Exited ternyata didapatkan persentase bahwa nasabah lebih banyak yang stay (tidak keluar) dibandingkan dengan yang keluar yakni sebesar 79.6%.

3. Multivariate Analysis¶

Lakukan multivariate analysis (seperti correlation heatmap dan category plots, sesuai yang diajarkan di kelas). Tuliskan hasil observasinya, seperti:¶

A. Bagaimana korelasi antara masing-masing feature dan label. Kira-kira feature mana saja yang paling relevan dan harus dipertahankan?

B. Bagaimana korelasi antar-feature, apakah ada pola yang menarik? Apa yang perlu dilakukan terhadap feature itu?

  • Tuliskan juga jika memang tidak ada feature yang saling berkorelasi
In [ ]:
import pandas as pd

data = pd.read_csv('Churn_Modelling.csv')

display(data)
RowNumber CustomerId Surname CreditScore Geography Gender Age Tenure Balance NumOfProducts HasCrCard IsActiveMember EstimatedSalary Exited
0 1 15634602 Hargrave 619 France Female 42 2 0.00 1 1 1 101348.88 1
1 2 15647311 Hill 608 Spain Female 41 1 83807.86 1 0 1 112542.58 0
2 3 15619304 Onio 502 France Female 42 8 159660.80 3 1 0 113931.57 1
3 4 15701354 Boni 699 France Female 39 1 0.00 2 0 0 93826.63 0
4 5 15737888 Mitchell 850 Spain Female 43 2 125510.82 1 1 1 79084.10 0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
9995 9996 15606229 Obijiaku 771 France Male 39 5 0.00 2 1 0 96270.64 0
9996 9997 15569892 Johnstone 516 France Male 35 10 57369.61 1 1 1 101699.77 0
9997 9998 15584532 Liu 709 France Female 36 7 0.00 1 0 1 42085.58 1
9998 9999 15682355 Sabbatini 772 Germany Male 42 3 75075.31 2 1 0 92888.52 1
9999 10000 15628319 Walker 792 France Female 28 4 130142.79 1 1 0 38190.78 0

10000 rows × 14 columns

In [ ]:
# Akses informasi umum pada data
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 10000 entries, 0 to 9999
Data columns (total 14 columns):
 #   Column           Non-Null Count  Dtype  
---  ------           --------------  -----  
 0   RowNumber        10000 non-null  int64  
 1   CustomerId       10000 non-null  int64  
 2   Surname          10000 non-null  object 
 3   CreditScore      10000 non-null  int64  
 4   Geography        10000 non-null  object 
 5   Gender           10000 non-null  object 
 6   Age              10000 non-null  int64  
 7   Tenure           10000 non-null  int64  
 8   Balance          10000 non-null  float64
 9   NumOfProducts    10000 non-null  int64  
 10  HasCrCard        10000 non-null  int64  
 11  IsActiveMember   10000 non-null  int64  
 12  EstimatedSalary  10000 non-null  float64
 13  Exited           10000 non-null  int64  
dtypes: float64(2), int64(9), object(3)
memory usage: 1.1+ MB
In [ ]:
# Hapus kolom RowNumber dan CustomerId
data = data.drop(columns = ['RowNumber', 'CustomerId'])

# Ubah beberapa tipe data berikut
data = data.astype({
    'HasCrCard' : 'object',
    'IsActiveMember' : 'object',
    'Exited' : 'object'
})

# Periksa kembali
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 10000 entries, 0 to 9999
Data columns (total 12 columns):
 #   Column           Non-Null Count  Dtype  
---  ------           --------------  -----  
 0   Surname          10000 non-null  object 
 1   CreditScore      10000 non-null  int64  
 2   Geography        10000 non-null  object 
 3   Gender           10000 non-null  object 
 4   Age              10000 non-null  int64  
 5   Tenure           10000 non-null  int64  
 6   Balance          10000 non-null  float64
 7   NumOfProducts    10000 non-null  int64  
 8   HasCrCard        10000 non-null  object 
 9   IsActiveMember   10000 non-null  object 
 10  EstimatedSalary  10000 non-null  float64
 11  Exited           10000 non-null  object 
dtypes: float64(2), int64(4), object(6)
memory usage: 937.6+ KB

A. Korelasi antar feature dan label (ANOVA)¶

In [ ]:
data.columns
Out[ ]:
Index(['Surname', 'CreditScore', 'Geography', 'Gender', 'Age', 'Tenure',
       'Balance', 'NumOfProducts', 'HasCrCard', 'IsActiveMember',
       'EstimatedSalary', 'Exited'],
      dtype='object')
In [ ]:
data[data['Exited'] == 1]['Age'].dropna()
Out[ ]:
0       42
2       42
5       44
7       29
16      58
        ..
9981    42
9982    46
9991    53
9997    36
9998    42
Name: Age, Length: 2037, dtype: int64
In [ ]:
group1 = data[data['Exited'] == 1]['Age'].dropna()
group2 = data[data['Exited'] == 0]['Age'].dropna()

print(group1.var(), group2.var())
95.28808400195597 102.52297408041709
In [ ]:
import pandas as pd
from scipy.stats import ttest_ind

# Membuat DataFrame contoh
data = {'Group': ['A', 'A', 'A', 'A', 'B', 'B', 'B', 'B'],
        'Score': [75, 80, 85, 90, 65, 70, 75, 80]}

df = pd.DataFrame(data)

# Memisahkan data berdasarkan kelompok
group_A = df[df['Group'] == 'A']['Score']
group_B = df[df['Group'] == 'B']['Score']

# Melakukan t-test independen
t_stat, p_value = ttest_ind(group_A, group_B)

# Menampilkan hasil
print("T-Statistic:", t_stat)
print("P-Value:", p_value)
T-Statistic: 2.1908902300206643
P-Value: 0.07098765432098764
In [ ]:
import numpy as np
import scipy.stats as stats

def HitungTtest(data, nama_kolom):
    # Define your data
    group_A = data[data['Exited'] == 1][nama_kolom]
    group_B = data[data['Exited'] == 0][nama_kolom]

    # Setting alpha (toleransi error)
    alpha = 0.05

    # Perform t-test dengan
    t_stat, p_value = stats.ttest_ind(group_A, group_B)

    # Print the effect size
    print(f'p-value : {p_value} dan t-stats : {t_stat}')
    if p_value >= alpha:
        print(f'''Hipotesis Null (H0) diterima, {nama_kolom} tidak berpengaruh terhadap keputusan customer untuk exit!''')
    else:
        print(f'''Hipotesis (H1) diterima, berarti cukup bukti statistik yang menyatakan bahwa ada perbedaan rata-rata {nama_kolom} terhadap keputusan pelanggan churn''')
In [ ]:
import pandas as pd

data = pd.read_csv('Churn_Modelling.csv')

data = data.drop(columns = ['RowNumber', 'CustomerId'])

# Ubah beberapa tipe data berikut
data = data.astype({
    'HasCrCard' : 'object',
    'IsActiveMember' : 'object',
    'Exited' : 'object'
})

int_columns = data.select_dtypes(include='int').columns

for col in int_columns:
   print(f'\nUji pengaruh {col} terhadap keputusan churn pelanggan\n')
   HitungTtest(data, col)
   print('----------------------------------------------------------')
Uji pengaruh CreditScore terhadap keputusan churn pelanggan

p-value : 0.006738213892192373 dan t-stats : -2.7100778888729833
Hipotesis (H1) diterima, berarti cukup bukti statistik yang menyatakan bahwa ada perbedaan rata-rata CreditScore terhadap keputusan pelanggan churn
----------------------------------------------------------

Uji pengaruh Age terhadap keputusan churn pelanggan

p-value : 1.2399313093427738e-186 dan t-stats : 29.76681499437077
Hipotesis (H1) diterima, berarti cukup bukti statistik yang menyatakan bahwa ada perbedaan rata-rata Age terhadap keputusan pelanggan churn
----------------------------------------------------------

Uji pengaruh Tenure terhadap keputusan churn pelanggan

p-value : 0.16152684949473256 dan t-stats : -1.4000584366735584
Hipotesis Null (H0) diterima, Tenure tidak berpengaruh terhadap keputusan customer untuk exit!
----------------------------------------------------------

Uji pengaruh NumOfProducts terhadap keputusan churn pelanggan

p-value : 1.717333004804293e-06 dan t-stats : -4.786984698423093
Hipotesis (H1) diterima, berarti cukup bukti statistik yang menyatakan bahwa ada perbedaan rata-rata NumOfProducts terhadap keputusan pelanggan churn
----------------------------------------------------------
In [ ]:
import math
from scipy.stats import chi2_contingency

alpha = 0.05
col_category = ['Gender', 'HasCrCard', 'IsActiveMember']

for col in col_category:
    # Melakukan proses crosstab
    cross_tab = pd.crosstab(data[col], data['Exited'])

    # Menghitung chi-squared test
    chi2, p_value, dof, expected = chi2_contingency(cross_tab)
    koefisien_kontingensi = math.sqrt(chi2/(chi2 + data.shape[0]))
    koefisien_kontingensi = round(koefisien_kontingensi, 4)

    # Menampilkan hasil
    print(f'\nUji Chi-Squared pada {col} terhadap Exited Status\n')
    display(cross_tab)

    print('\nChi-squared:', chi2)
    print('P-value:', p_value)
    print('Degrees of Freedom:', dof)
    print('Expected Values:\n')
    display(pd.DataFrame(expected, columns=cross_tab.columns, index=cross_tab.index))

    if p_value >= alpha:
        print(f'''Hipotesis Null (H0) diterima, {col} tidak berpengaruh terhadap keputusan customer untuk exit!''')
    else:
        print(f'''Hipotesis (H1) diterima, berarti cukup bukti statistik yang menyatakan bahwa ada pengaruh {col} terhadap keputusan pelanggan exited''')
        print(f'Effect size sebesar {koefisien_kontingensi*100}%')
    print('------------------------------------------------------------')
Uji Chi-Squared pada Gender terhadap Exited Status

Exited 0 1
Gender
Female 3404 1139
Male 4559 898
Chi-squared: 112.91857062096116
P-value: 2.2482100097131755e-26
Degrees of Freedom: 1
Expected Values:

Exited 0 1
Gender
Female 3617.5909 925.4091
Male 4345.4091 1111.5909
Hipotesis (H1) diterima, berarti cukup bukti statistik yang menyatakan bahwa ada pengaruh Gender terhadap keputusan pelanggan exited
Effect size sebesar 10.57%
------------------------------------------------------------

Uji Chi-Squared pada HasCrCard terhadap Exited Status

Exited 0 1
HasCrCard
0 2332 613
1 5631 1424
Chi-squared: 0.47133779904440803
P-value: 0.49237236141554686
Degrees of Freedom: 1
Expected Values:

Exited 0 1
HasCrCard
0 2345.1035 599.8965
1 5617.8965 1437.1035
Hipotesis Null (H0) diterima, HasCrCard tidak berpengaruh terhadap keputusan customer untuk exit!
------------------------------------------------------------

Uji Chi-Squared pada IsActiveMember terhadap Exited Status

Exited 0 1
IsActiveMember
0 3547 1302
1 4416 735
Chi-squared: 242.98534164287963
P-value: 8.785858269303703e-55
Degrees of Freedom: 1
Expected Values:

Exited 0 1
IsActiveMember
0 3861.2587 987.7413
1 4101.7413 1049.2587
Hipotesis (H1) diterima, berarti cukup bukti statistik yang menyatakan bahwa ada pengaruh IsActiveMember terhadap keputusan pelanggan exited
Effect size sebesar 15.4%
------------------------------------------------------------
In [ ]:
import pandas as pd
from scipy.stats import chi2_contingency

# Membuat DataFrame contoh
data = {'Category': ['A', 'B', 'A', 'B', 'A'],
        'Outcome': ['Success', 'Failure', 'Failure', 'Success', 'Success']}
df = pd.DataFrame(data)

# Menghitung cross-tabulation
cross_tab = pd.crosstab(df['Category'], df['Outcome'])

# Menghitung chi-squared test
chi2, p_value, dof, expected = chi2_contingency(cross_tab)

# Menampilkan hasil
print('Chi-squared:', chi2)
print('P-value:', p_value)
print('Degrees of Freedom:', dof)
print('Expected Values:')
print(pd.DataFrame(expected, columns=cross_tab.columns, index=cross_tab.index))
Chi-squared: 0.0
P-value: 1.0
Degrees of Freedom: 1
Expected Values:
Outcome   Failure  Success
Category                  
A             1.2      1.8
B             0.8      1.2

B. Kolerasi antar feature (HEATMAP)¶

In [ ]:
import pandas as pd
import matplotlib.pyplot as plt

data = pd.read_csv('Churn_Modelling.csv')
In [ ]:
import plotly.express as px

data = data.astype({
    'Exited' : 'int'
})
correlation = data.corr()

fig = px.imshow(correlation, text_auto=True)

fig.show()
<ipython-input-23-0e6a7da19a08>:6: FutureWarning:

The default value of numeric_only in DataFrame.corr is deprecated. In a future version, it will default to False. Select only valid columns or specify the value of numeric_only to silence this warning.

In [ ]:
import plotly.express as px

correlation = data.corr().round(4)

fig = px.imshow(
    correlation,
    color_continuous_scale='Purples',
    text_auto=True
)

fig.update_layout(
    title='Correlation Heatmap',
    plot_bgcolor='rgba(0,0,0,0)',  # Set transparent background
    showlegend=False  # Hide the legend
)

fig.show()
<ipython-input-24-22e838a29a22>:3: FutureWarning:

The default value of numeric_only in DataFrame.corr is deprecated. In a future version, it will default to False. Select only valid columns or specify the value of numeric_only to silence this warning.

dari grafik diatas terlihat bahwa :

  1. Feature age dan belance memiliki hubungan korelasi positif yang lemah sebesar 0,02 itu menunjukkan korelasi yang sangat lemah atau tidak ada korelasi yang signifikan antara age dan balance. Dalam hal ini, tidak ada hubungan linier yang jelas antara usia dan saldo.

  2. Feture numofproduct dan belance memiliki hubungan korelasi negatif yang lemah sebesar -0,3. Hal ini dapat diartikan bahwa semakin banyak produk yang dimiliki oleh seorang nasabah, cenderung memiliki saldo yang lebih rendah.

  3. Feature age dan exited memiliki hubungan korelasi positif yang lemah sebesar 0,28. Hal ini dapat diartikan bahwa umur yang semakin tua memiliki kecenderungan untuk churn.

  4. Feature balance dan exited memiliki hubungan korelasi positif yang lemah sebesar 0,11. Hal ini dapat diartikan bahwa nasabah yang memiliki saldo rendah cenderung akan churn.

4. Business Insight¶

Selain EDA, lakukan juga beberapa analisis dan visualisasi untuk menemukan suatu business insight. Tuliskan minimal 3 insight, dan berdasarkan insight tersebut jelaskan rekomendasinya untuk bisnis.¶

Insight 1: Visualisasi tingkat churn pada grup usia¶

In [ ]:
 import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

data = pd.read_csv('Churn_Modelling.csv')

fig, ax = plt.subplots(
    figsize = (10 , 5)
)
# Filter data dan assign ke variabel berikut
data_exited=  data[data['Exited'] == 1]
data_stayed =data[data['Exited'] == 0]

# Buat plot untuk data age pada data yang churned (beri warna A)
sns.kdeplot(
    data = data_stayed['Age'] ,
    color = 'blue' ,
    label = 'Exited= No',
    legend = True,
    ax = ax
)

# Buat plot untuk data age pada data yang no churned (beri warna B)
sns.kdeplot(
    data = data_exited['Age'],
    color = 'red' ,
    label = 'Exited= Yes' ,
    legend = True,
    ax = ax
)

# Menghapus tepian
sns.despine()

# Set title
ax.set_title(
    label = 'Visualisasi tingkat churn pada grup umur',
    color = 'black' ,
    fontsize = 16,
    fontweight = 'bold'
)
# Set label
ax.set_xlabel(
    xlabel = 'Age',
    fontsize = 12
)

ax.set_ylabel(
    ylabel = 'Tingkat Churn',
    fontsize = 12
)

# Tampilkan legend
ax.legend()

# Atur ukuran ticks pada axis
plt.tick_params(
    axis = 'both',
    which = 'major',
    labelsize = 10
)

# Tampilkan grafik
plt.show()
No description has been provided for this image

INSIGHT 1 : Dapat dilihat bahwa sebagian besar pelanggan bank berada di kelompok umur 30-40 tahun, diikuti oleh kelompok umur 40-50 tahun, dan juga dapat melihat bahwa ada beberapa pelanggan bank yang berumur di atas 80 tahun, tetapi jumlahnya sangat sedikit. Namun, jika kita melihat tingkat churn dari masing-masing kelompok umur, kita dapat melihat bahwa pelanggan yang umurnya lebih muda memiliki tingkat churn yang lebih tinggi daripada pelanggan yang umurnya lebih tua. Hal ini menunjukkan bahwa pelanggan yang umurnya lebih muda cenderung lebih mudah berpindah ke bank lain yang menawarkan layanan yang lebih sesuai dengan gaya hidup mereka, seperti online banking, mobile banking, dll.

REKOMENDASI :

  • Membuat segmentasi pelanggan berdasarkan umur dan menyesuaikan penawaran produk atau layanan yang sesuai dengan kebutuhan dan preferensi mereka2. Misalnya, pelanggan yang lebih muda mungkin lebih tertarik dengan fitur digital dan inovatif, sedangkan pelanggan yang lebih tua mungkin lebih menghargai layanan personal dan konsultasi.
  • Meningkatkan loyalitas pelanggan dengan memberikan insentif atau reward kepada pelanggan yang telah lama menjadi nasabah bank3. Misalnya, memberikan diskon, cashback, poin, atau hadiah lainnya yang dapat ditukar dengan produk atau layanan bank.
  • Membangun hubungan yang kuat dengan pelanggan dengan melakukan komunikasi yang efektif dan responsif. Misalnya, memberikan saran atau solusi yang bermanfaat, mengirimkan pesan atau email yang ramah dan personal, atau menghubungi pelanggan secara berkala untuk mengetahui kepuasan dan masalah mereka.
  • Meningkatkan kualitas produk atau layanan dengan melakukan survei kepuasan pelanggan dan menganalisis feedback mereka. Misalnya, menanyakan tentang tingkat kepuasan, harapan, dan saran mereka terhadap produk atau layanan bank, dan melakukan perbaikan atau peningkatan sesuai dengan hasil survei.

Insight 2: Visualisasi hubungan saldo rata-rata dengan churn¶

In [ ]:
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

data = pd.read_csv('Churn_Modelling.csv')

fig, ax = plt.subplots(
    figsize = (10 , 5)
)
# Filter data dan assign ke variabel berikut
data_exited=  data[data['Exited'] == 1]
data_stayed =data[data['Exited'] == 0]

# Buat plot untuk data balance pada data yang churned (beri warna A)
sns.kdeplot(
    data = data_stayed['Balance'] ,
    color = 'green' ,
    label = 'Exited= No',
    legend = True,
    ax = ax
)

# Buat plot untuk data balance pada data yang no churned (beri warna B)
sns.kdeplot(
    data = data_exited['Balance'],
    color = 'red' ,
    label = 'Exited= Yes' ,
    legend = True,
    ax = ax
)

# Menghapus tepian
sns.despine()

# Set title
ax.set_title(
    label = 'Visualisasi tingkat churn pada balance',
    color = 'black' ,
    fontsize = 16,
    fontweight = 'bold'
)
# Set label
ax.set_xlabel(
    xlabel = 'Balance',
    fontsize = 12
)

ax.set_ylabel(
    ylabel = 'Tingkat Churn',
    fontsize = 12
)

# Tampilkan legend
ax.legend()

# Atur ukuran ticks pada axis
plt.tick_params(
    axis = 'both',
    which = 'major',
    labelsize = 10
)

# Tampilkan grafik
plt.show()
No description has been provided for this image

INSIGHT 2 : dapat di lihat bahwa sebagian besar pelanggan bank memiliki saldo rendah, antara 0 sampai 50.000 euro, dan juga dapat dilihat bahwa ada beberapa pelanggan bank yang memiliki saldo tinggi, di atas 200.000 euro, tetapi jumlahnya sangat sedikit. Pelanggan yang churn memiliki puncak distribusi saldo di sekitar 0 dan 100.000, sedangkan pelanggan yang tidak churn memiliki puncak distribusi saldo di sekitar 0 dan 75.000. Ini bisa berarti bahwa pelanggan yang churn cenderung lebih ekstrem dalam mengelola saldo mereka, baik terlalu rendah atau terlalu tinggi, sedangkan pelanggan yang tidak churn cenderung lebih moderat.

REKOMENDASI :

  • Bank perlu meningkatkan kualitas layanan dan memberikan penawaran yang menarik kepada pelanggan yang memiliki saldo tinggi, agar mereka tidak mudah beralih ke bank lain atau mengurangi transaksi mereka.
  • Bank perlu melakukan segmentasi pelanggan berdasarkan saldo dan faktor lainnya, dan menyesuaikan produk atau layanan yang sesuai dengan kebutuhan dan preferensi mereka.
  • Bank perlu melakukan komunikasi yang efektif dan responsif kepada pelanggan yang memiliki saldo rendah, agar mereka merasa dihargai dan diberikan solusi atau saran yang bermanfaat.

Insight 3: Visualisasi hubungan antara tenure dan churn¶

In [ ]:
 feedback_churn = data.groupby('Tenure')['Exited'].mean()
feedback_churn.plot(kind='bar')
plt.title('Tingkat Churn berdasarkan Tenure')
plt.xlabel('Tenure')
plt.ylabel('Tingkat Churn')
plt.show()
No description has been provided for this image

INSIGHT 3 : Dari visualisasi diatas dapat disimpulkan bahwa tenure tidak terlalu besar mempengaruhi churn.

  • Tingkat churn tertinggi terjadi pada pelanggan yang memiliki tenure 1 bulan (0.38) dan 9 bulan (0.36), sedangkan tingkat churn terendah terjadi pada pelanggan yang memiliki tenure 72 bulan (0.02).
  • Ada kecenderungan bahwa semakin lama masa berlangganan pelanggan, semakin rendah tingkat churn mereka. Ini bisa berarti bahwa pelanggan yang telah lama menggunakan layanan bank merasa puas dan loyal, sehingga tidak mudah beralih ke bank lain atau mengurangi transaksi mereka.
  • Namun, ada beberapa pengecualian, seperti pelanggan yang memiliki tenure 2 bulan dan 8 bulan memiliki tingkat churn yang lebih rendah daripada pelanggan yang memiliki tenure 3 bulan dan 7 bulan. Ini bisa berarti bahwa ada faktor lain selain tenure yang mempengaruhi keputusan pelanggan untuk churn, seperti produk, aktivitas, atau kepuasan.

REKOMENDASI

  • Bank perlu meningkatkan kualitas layanan dan memberikan penawaran yang menarik kepada pelanggan baru atau pelanggan yang memiliki tenure pendek, agar mereka tidak mudah beralih ke bank lain atau mengurangi transaksi mereka.
  • Bank perlu melakukan segmentasi pelanggan berdasarkan tenure dan faktor lainnya, dan menyesuaikan produk atau layanan yang sesuai dengan kebutuhan dan preferensi mereka.
  • Bank perlu melakukan komunikasi yang efektif dan responsif kepada pelanggan yang memiliki tenure panjang, agar mereka merasa dihargai dan diberikan solusi atau saran yang bermanfaat.

REKOMENDASI BISNIS

5. Git¶

Upload project teman-teman di sebuah repository git. Berkolaborasilah di Git jika ada perubahan version dari waktu ke waktu.

A.Buat Repository Git

B.Upload file notebook atau file pengerjaan lainnya pada repository tersebut

Untuk file README, dapat merupakan summary insight yang telah didapatkan dari EDA.

In [ ]:
https://github.com/MarcellinaFransisca/HWEDA-Kelompok8A